#!/usr/bin/perl
# -*- mode: perl; -*-
#
# Author: Jim Turner <jim@nukethemfromorbit.com>
#
# Can I turn a number into it's spelled-out equivalent?
#
#######################################################
#
# Pre-defined data
%segVals = ( '0' => '',
	     '1' => 'thousand, ',
	     '2' => 'million, ',
	     '3' => 'billion, ',
	     '4' => 'trillion, ',
	     '5' => 'quadrillion, ',
	     '6' => 'quintillion, ',
	     '7' => 'sextillion, ',
	     '8' => 'septillion, ',
	     '9' => 'octillion, ',
	    '10' => 'nonillion, ',
	    '11' => 'decillion, '
	    );

%numVals = ( '1' => [ 'one hundred', 'ten', 'one' ],
	     '2' => [ 'two hundred', 'twenty', 'two' ],
	     '3' => [ 'three hundred', 'thirty', 'three' ],
	     '4' => [ 'four hundred', 'fourty', 'four' ],
	     '5' => [ 'five hundred', 'fifty', 'five' ],
	     '6' => [ 'six hundred', 'sixty', 'six' ],
	     '7' => [ 'seven hundred', 'seventy', 'seven' ],
	     '8' => [ 'eight hundred', 'eighty', 'eight' ],
	     '9' => [ 'nine hundred', 'ninety', 'nine' ],
	     '0' => [ 'zero', 'zero', 'zero' ],
	 );


#
#######################################################
my $number = $ARGV[0];
if( $number eq "" )
{
    print "I need a number\n";
    exit();
}

# First, remove any trash
$number =~ s/\,//g;
$number =~ s/\-//g;

die( 'Invalid characters in number' ) if( $number !~ /^\d+$/ );

if( length( $number ) > 36 )
{
    print "Too damn big... I go up to 10^33.  If that's not big enough,\n";
    print "edit \%segVals and this if().\n\n";
    exit();

    # http://www.unc.edu/~rowlett/units/large.html
}

# Then, reverse the number, and break it up into 3's
my $r_num = reverse $number;
for( my $x=0; $x<length( $r_num ); $x+=3 )
{
    my $part = reverse substr( $r_num, $x, 3 );
    push( @segments, $part );
}

for( $y=$#segments; $y>=0; $y-- )
{
    my( $p1, $p2, $p3 ) = split( //, $segments[$y] );

    if( $p3 eq "" && $p2 eq "" )
    {
	$p3 = $p1;
	$p1 = "";
    }
    if( $p3 eq "" )
    {
	$p3 = $p2;
	$p2 = $p1;
	$p1 = "";
    }

    my $p1_desc = _getDesc( $p1, 1 ) if( $p1 );

    # handle teens
    my $p2_desc;
    if( $p2 == 1 )
    {
	$p2_desc = _getTeens( $p2, $p3 );
	$p3 = 0;
    }
    else
    {
	$p2_desc = _getDesc( $p2, 2 ) if( $p2 );
    }

    # Handle zero
    my $p3_desc;
    if( ($p3 == 0) && (length( $number ) == 1) )
    {
	$p3_desc = _getDesc( "$p3", 3 );
    }
    else
    {
	$p3_desc = _getDesc( $p3, 3 ) if( $p3 );
    }

    my $seg_desc = _getDesc( $y, "segment" );


    $string_value .= "$p1_desc " if( $p1_desc );
    $string_value .= "$p2_desc " if( $p2_desc );
    $string_value .= "$p3_desc " if( $p3_desc );

    if( $seg_desc )
    {
	# Only print the seg_desc if a part_desc was used... 
	$string_value .= "$seg_desc" if( $p1_desc || $p2_desc || $p3_desc );
    }
}

$string_value =~ s/ +$//;
print "$string_value\n";

#####################################################

sub _getTeens
{
    my( $tens, $ones ) = @_;

    my $val = $tens.$ones;

    for( $val )
    {
	/^10$/ and do{ return "ten";       };
	/^11$/ and do{ return "eleven";    };
	/^12$/ and do{ return "twelve";    };
	/^13$/ and do{ return "thirteen";  };
	/^14$/ and do{ return "fourteen";  };
	/^15$/ and do{ return "fifteen";   };
	/^16$/ and do{ return "sixteen";   };
	/^17$/ and do{ return "seventeen"; };
	/^18$/ and do{ return "eighteen";  };
	/^19$/ and do{ return "nineteen";  };
    }
}
#####################################################

sub _getDesc
{
    my( $val, $pos ) = @_;

    if( $pos eq "segment" )
    {
	return( $segVals{$val} );
    }
    else
    {
	return( $numVals{$val}[$pos-1] );
    }
}
#####################################################



